package com.homelock.service;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONArray;
import com.aliyuncs.dysmsapi.model.v20170525.SendBatchSmsResponse;
import com.homelock.common.enumeration.TriggerTypeEnum;
import com.homelock.constants.DevUserRoleEnum;
import com.homelock.entity.*;
import com.homelock.thread.AsyncTask;
import com.homelock.vo.DevCommunityVo;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.homelock.common.enumeration.SmsSendTypeEnum;
import com.homelock.common.util.AliYunComSms;
import com.homelock.domain.sms.ActiveSms;
import com.pi.base.dto.result.ServiceResult;
import com.pi.uc.dao.entity.UcUserEntity;
import com.pi.uc.service.UcUserService;
import org.springframework.util.CollectionUtils;

/**
 * 短信发送
 * @author chenmfa
 */
@Service
public class SmsSendApiService {
    private static final Logger logger = LoggerFactory.getLogger(SmsSendApiService.class);


    private static final String MSG_TAG = "ALIYUN";
    private static final String REGION = "86";
    private static final String SIGN = "科银管家";
    private static final String SMS_SUB_TYPE = "";
    private static final String SEND_TARGET_NAME = "";
    private static final String MAP_PARAMER_USERNAME = "username";
    /**
     * 模版内容: 亲爱的（${notifyUser}），“小科”紧急提醒：“${triggerUser}”用户已触发${alarmName}报警功能，请您尽快归家或联系物业处理！
     * 变量属性: notifyUser-其他；triggerUser-其他；alarmName-其他；
     */
    private static final String MAP_PARAMER_NOTIFYUSER = "notifyUser";
    private static final String MAP_PARAMER_TRRIGGERUSER = "triggerUser";
    private static final String MAP_PARAMER_ALARMUSER = "alarmName";
    /**
     * 亲情短信对应的开门用户
     */
    private static final String MAP_PARAMER_LINKUSER = "linkUser";
    private static final int MAX_NUM = 1000;


    private HlDevInfoService devInfoService;
    
    private UcUserService userService;
    
    private UserCommunityService userCommunityService;

    private UserEmergencyService userEmergencyService;

    private LockUserService lockUserService;

    private HlCommunityHouseholdService hlCommunityHouseholdService;

    private AsyncTask asyncTask;
    
    @Autowired
    public SmsSendApiService(
            HlDevInfoService devInfoService,
            UcUserService userService, 
            UserCommunityService userCommunityService,
            UserEmergencyService userEmergencyService,
            LockUserService lockUserService,
            HlCommunityHouseholdService hlCommunityHouseholdService,
            AsyncTask asyncTask){
        Assert.notNull(devInfoService, "门锁服务为空");
        Assert.notNull(userService, "用户服务为空");
        Assert.notNull(userCommunityService, "社区服务为空");
        Assert.notNull(userEmergencyService, "紧急联系人服务为空");
        Assert.notNull(lockUserService, "锁具用户服务为空");
        this.devInfoService = devInfoService;
        this.userService = userService;
        this.userCommunityService = userCommunityService;
        this.userEmergencyService = userEmergencyService;
        this.lockUserService = lockUserService;
        this.hlCommunityHouseholdService = hlCommunityHouseholdService;
        this.asyncTask = asyncTask;
    }

    /**
     * @deprecated
     * @param devId
     * @param smsSendTypeEnum
     */
    public void sendAlarm(Long devId, SmsSendTypeEnum smsSendTypeEnum){
        HlDevInfo devInfo = devInfoService.getDevInfobyIdIfExist(devId);
        if(null == devInfo){
            logger.info("[dev_expire] 设备不存在或者已删除, {}", devId);
            return;
        }
        UcUserEntity owner = userService.queryUserInfo(devInfo.getOwnerId());
        if(null == owner){
            return;
        }
        ActiveSms sms = newInstance(owner.getSourceId(),smsSendTypeEnum);
        Map<String,String> map = new HashMap<String, String>();
        map.put("username", owner.getNickName());
        sms.setSmsVarMap(map);

        if(null != owner && StringUtils.isNotBlank(owner.getMobile())){
            sms.setPhoneNumber(owner.getMobile());
            ServiceResult<String> ownerResult = AliYunComSms.sendSms(sms);
            logger.info("[sms_owner] 给主人发送短信, {}", ownerResult);
        }
        
        DevCommunityVo devCommunity = userCommunityService.listDevCommunityDetail(devInfo.getId());
        if(null != devCommunity && StringUtils.isNotBlank(devCommunity.getContact())){
            sms.setPhoneNumber(devCommunity.getContact());
            ServiceResult<String> ownerResult = AliYunComSms.sendSms(sms);
            logger.info("[sms_community] 给社区发送短信, {}", ownerResult);
        }
    }


    /**
     * 发送报警消息
     * 紧急联系人，注册人，物业
     * @param devInfo 设备信息
     * @param triggerTypeEnum 报警类型 指纹报警（有开门用户），密码报警，禁试报警，假锁报警
     * @param openUserName 开门用户 （无该用户则使用空字符串）
     */
    public void sendAlarmSms(HlDevInfo devInfo, TriggerTypeEnum triggerTypeEnum,String openUserName){
        openUserName = (openUserName == null) ? "" :openUserName;
        UcUserEntity owner = userService.queryUserInfo(devInfo.getOwnerId());
        if(owner != null){
            String triggerType = triggerTypeEnum.getName();
            String alarmName = triggerType.substring(0,triggerType.length()-2);
            Long sourceId = owner.getSourceId();
            ActiveSms sms = generateAlarmCommonSms(sourceId);
            sendToLockOwner(sms,owner,openUserName,alarmName);
            sendToEmergencyContacter(sms,owner,openUserName,alarmName);
            sendToCommunity(sms,devInfo,openUserName,alarmName);
        }
    }

    /**
     * 发送亲情报警短信
     * @param devInfo
     * @param sender
     * @param familyLinkages
     */
    public void sendFamilySms(HlDevInfo devInfo, HlDevUser sender, List<HlFamilyLinkage> familyLinkages){
        if(!CollectionUtils.isEmpty(familyLinkages)){
            List<Long> lockUserIds = familyLinkages.stream().map(HlFamilyLinkage::getTargetUserId).collect(Collectors.toList());
            List<HlDevUser> receivers = lockUserService.queryLockUserListByIds(devInfo.getId(),lockUserIds);
            if(CollectionUtils.isEmpty(receivers)){
                logger.info("[family_receiver] 没有亲情接收方, {},{}", devInfo.getId(),sender.getId());
            }
            ActiveSms sms = generateFaminlySms(devInfo.getSourceId());

            for(HlDevUser receiver:receivers){
                if(!StringUtils.isBlank(receiver.getMobile())) {
                    sms = initParamToFamilyCommonSms(sms, receiver.getMobile(),receiver.getDevUserName(), sender.getDevUserName() );
                    ServiceResult<String> ownerResult = AliYunComSms.sendSms(sms);
                    logger.info("[sms_owner] 给亲情接收人{}发送短信, {}", receiver.getId(),ownerResult);
                }
            }
        }
    }

    /**
     * 给注册人发短信
     * @param sms
     * @param owner
     */
    private void sendToLockOwner(ActiveSms sms,UcUserEntity owner,String openUserName,String alarmType){
        if(null != owner && StringUtils.isNotBlank(owner.getMobile())){
            sms = initParamToAlarmCommonSms(sms,owner.getMobile(),owner.getNickName(),openUserName,alarmType);
            ServiceResult<String> ownerResult = AliYunComSms.sendSms(sms);
            logger.info("[sms_owner] 给注册人发送短信, {}", ownerResult);
        }
    }


    /**
     * @deprecated
     * 给管理员发短信
     * @update 20190930 18:18 暂时不将报警消息发送给管理员
     * @param sms
     * @param devId
     */
    private void sendToLockAdmin(ActiveSms sms,Long devId){
        // 查询锁具管理员（有多个管理员的情况）
        List<HlDevUser> list = lockUserService.queryUsersByDevIdAndRole(devId, DevUserRoleEnum.ADMIN.getRole());
        if(CollectionUtils.isEmpty(list)){
            return;
        }
        for(int i = 0; i < list.size(); i++){
            sendSingleAdminAlarm(sms,list.get(i).getMobile(),list.get(i).getDevUserName());
        }
    }

    private void sendSingleAdminAlarm(ActiveSms sms,String phone,String nickName){
        if(StringUtils.isBlank(phone)){
            return;
        }
        Map<String, String> map = new HashMap<String, String>();
        map.put(MAP_PARAMER_USERNAME, nickName);
        sms.setSmsVarMap(map);
        sms.setPhoneNumber(phone);
        ServiceResult<String> ownerResult = AliYunComSms.sendSms(sms);
        logger.info("[sms_admin] 给管理员发送短信, {}", ownerResult);
    }

    /**
     * 给紧急联系人发送报警消息
     * @param sms
     */
    private void sendToEmergencyContacter(ActiveSms sms,UcUserEntity owner,String openUserName,String alarmType){
        // 查询紧急联系人
        UcUserEmergency userEmergency = userEmergencyService.info(owner.getId());
        if(userEmergency != null){
           /* Map<String, String> map = new HashMap<String, String>();
            map.put(MAP_PARAMER_USERNAME, userEmergency.getContactName());
            sms.setSmsVarMap(map);
            sms.setPhoneNumber(userEmergency.getContactMobile());*/
            sms = initParamToAlarmCommonSms(sms,userEmergency.getContactMobile(),userEmergency.getContactName(),openUserName,alarmType);
            ServiceResult<String> ownerResult = AliYunComSms.sendSms(sms);
            logger.info("[sms_emergency] 给紧急联系人发送短信, {}", ownerResult);
        }
    }

    /**
     * 给社区推送报警短信
     * @param sms
     */
    private void sendToCommunity(ActiveSms sms,HlDevInfo devInfo,String openUserName,String alarmType){
       DevCommunityVo devCommunityVo = userCommunityService.listDevCommunityDetail(devInfo.getId());
        if(null != devCommunityVo && StringUtils.isNotBlank(devCommunityVo.getContact())){
            sms = initParamToAlarmCommonSms(sms,devCommunityVo.getContact(),devCommunityVo.getCommunityName(),openUserName,alarmType);
           /* sms.setPhoneNumber(devCommunityVo.getContact());*/
            ServiceResult<String> ownerResult = AliYunComSms.sendSms(sms);
            logger.info("[sms_owner] 给社区发送短信, {}", ownerResult);
        }
    }


    public void sendCommunityNotice(Long communityId,List<String> phoneNumList,String content){
        // 批量发送短信，每次最多发送1000条(MAX_NUM)
        int sendTimeNum = phoneNumList.size()/MAX_NUM +1 ;
        List<String> sendList = new ArrayList<>(MAX_NUM);
        List<Map> params = new ArrayList<>(MAX_NUM);
        Map<String,String> param = new HashMap<String, String>(){{
            put("username",content);
        }};
        ActiveSms activeSms = newInstance(communityId,SmsSendTypeEnum.UNLOCK_ALARM);
        activeSms.setPhoneNumber("");
        List<SendBatchSmsResponse> resultList = new ArrayList<>(sendTimeNum);
        // 发送短信，记录返回的数据
        for(int i = 0;i<phoneNumList.size();i++){
            sendList.add(phoneNumList.get(i));
            params.add(param);
            // 是否是最后一次
            if(i == phoneNumList.size()-1){
                SendBatchSmsResponse response =  sendNotice(activeSms,sendList,params);
                resultList.add(response);
                break;
            }
            if(sendList.size() == MAX_NUM){
                // 达到可发送值
                SendBatchSmsResponse response =  sendNotice(activeSms,sendList,params);
                resultList.add(response);
                // 清空手机号
                sendList.clear();
                params.clear();
            }
        }

        // 更新短信可发送数
        int currentSendNum = hlCommunityHouseholdService.querySmsSendNumByCommunityId(communityId);
        hlCommunityHouseholdService.insertOrUpdateSmsSendNum(communityId,currentSendNum-phoneNumList.size());
        // 异步log
        asyncTask.logSmsSendRecord(phoneNumList.size(),resultList,content,communityId);
    }

    public SendBatchSmsResponse sendNotice(ActiveSms activeSms,List sendList,List  params){
        ServiceResult<SendBatchSmsResponse> result = AliYunComSms.sendBatchSms(activeSms,sendList,params);
        return result.getData();
    }

    /**
     * 构造通用的亲情模板
     * @param sendPhone
     * @param notifyUser
     * @param linkUser
     * @return
     * 通用的锁具亲情信息
     * 模版类型: 短信通知
     * 模版名称: 通用报警
     * 模版CODE: SMS_
     */
    public ActiveSms initParamToFamilyCommonSms(ActiveSms sms,String sendPhone,String notifyUser,String linkUser){
        Map<String,String> map = new HashMap();
        map.put(MAP_PARAMER_NOTIFYUSER,notifyUser);
        map.put(MAP_PARAMER_LINKUSER,linkUser);
        sms.setSmsVarMap(map);
        sms.setPhoneNumber(sendPhone);
        return sms;
    }

    /**
     * 构造通用的报警模板
     * @param sendPhone
     * @param notifyUser
     * @param triggerUser
     * @param alarmName
     * @return
     * 通用的锁具报警信息
     * 模版类型: 短信通知
     * 模版名称: 通用报警
     * 模版CODE: SMS_175581078
     * 模版内容: 亲爱的（${notifyUser}），“小科”紧急提醒：“${triggerUser}”用户已触发${alarmName}报警功能，请您尽快归家或联系物业处理！
     * 变量属性: notifyUser-其他；triggerUser-其他；alarmName-其他；
     */
    public ActiveSms initParamToAlarmCommonSms(ActiveSms sms,String sendPhone,String notifyUser,String triggerUser,String alarmName){
        Map<String,String> map = new HashMap();
        map.put(MAP_PARAMER_NOTIFYUSER,notifyUser);
        map.put(MAP_PARAMER_TRRIGGERUSER,triggerUser);
        map.put(MAP_PARAMER_ALARMUSER,alarmName);
        sms.setSmsVarMap(map);
        sms.setPhoneNumber(sendPhone);
        return sms;
    }

    /**
     * initq亲情SMS
     * @param sourceId
     * @return
     */
    private ActiveSms generateFaminlySms(Long sourceId){
        return  newInstance(sourceId,SmsSendTypeEnum.FAMILY_MSG);
    }

    /**
     * init报警SMS
     * @param sourceId
     * @return
     */
    private ActiveSms generateAlarmCommonSms(Long sourceId){
        return newInstance(sourceId,SmsSendTypeEnum.COMMON_ALARM);
    }

    private ActiveSms newInstance(Long sourceId,SmsSendTypeEnum smsSendTypeEnum){
        ActiveSms sms = new ActiveSms();
        sms.setMsgTag(MSG_TAG);
        sms.setRegion(REGION);
        sms.setSign(SIGN);
        sms.setSmsSubType(SMS_SUB_TYPE);
        sms.setSmsTemplateCode(smsSendTypeEnum.getTemplate());
       /* Map<String,String> map = new HashMap<String, String>();*/
        /*map.put("username", owner.getNickName());
        sms.setSmsVarMap(map);*/
        sms.setSourceId(sourceId);
        return sms;
    }

}
